#include "qtvrGUIMain.h"
#include <wx/msgdlg.h>

//(*InternalHeaders(qtvrGUIDialog)
#include <wx/settings.h>
#include <wx/font.h>
#include <wx/intl.h>
#include <wx/string.h>
//*)

//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

//(*IdInit(qtvrGUIDialog)
const long qtvrGUIDialog::ID_TEXTCTRL1 = wxNewId();
const long qtvrGUIDialog::ID_BUTTON1 = wxNewId();
const long qtvrGUIDialog::ID_HTMLWINDOW1 = wxNewId();
const long qtvrGUIDialog::ID_SPINCTRL2 = wxNewId();
const long qtvrGUIDialog::ID_STATICTEXT2 = wxNewId();
const long qtvrGUIDialog::ID_SPINCTRL1 = wxNewId();
const long qtvrGUIDialog::ID_STATICTEXT1 = wxNewId();
const long qtvrGUIDialog::ID_CHECKBOX1 = wxNewId();
const long qtvrGUIDialog::ID_CHECKBOX2 = wxNewId();
const long qtvrGUIDialog::ID_BUTTON3 = wxNewId();
const long qtvrGUIDialog::ID_TEXTCTRL2 = wxNewId();
const long qtvrGUIDialog::ID_BUTTON2 = wxNewId();
//*)

BEGIN_EVENT_TABLE(qtvrGUIDialog,wxDialog)
    //(*EventTable(qtvrGUIDialog)
    //*)
END_EVENT_TABLE()

qtvrGUIDialog::qtvrGUIDialog(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(qtvrGUIDialog)
    Create(parent, wxID_ANY, _(" mkqtGUI"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX, _T("wxID_ANY"));
    Move(wxPoint(-1,-1));
    FlexGridSizer1 = new wxFlexGridSizer(0, 1, 0, 0);
    FlexGridSizer1->AddGrowableCol(0);
    FlexGridSizer1->AddGrowableRow(1);
    StaticBoxSizer2 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Working Directory"));
    FlexGridSizer2 = new wxFlexGridSizer(0, 2, 0, 0);
    FlexGridSizer2->AddGrowableCol(0);
    TextCtrlDirecory = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
    TextCtrlDirecory->Disable();
    FlexGridSizer2->Add(TextCtrlDirecory, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    ButtonBrowse = new wxButton(this, ID_BUTTON1, _("Browse..."), wxDefaultPosition, wxSize(93,23), 0, wxDefaultValidator, _T("ID_BUTTON1"));
    FlexGridSizer2->Add(ButtonBrowse, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    StaticBoxSizer2->Add(FlexGridSizer2, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer1->Add(StaticBoxSizer2, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    StaticBoxSizer1 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Content"));
    FlexGridSizer3 = new wxFlexGridSizer(0, 2, 0, 0);
    FlexGridSizer3->AddGrowableCol(0);
    FlexGridSizer3->AddGrowableRow(0);
    HtmlWindowPreview = new wxHtmlWindow(this, ID_HTMLWINDOW1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO|wxSIMPLE_BORDER, _T("ID_HTMLWINDOW1"));
    HtmlWindowPreview->SetMinSize(wxSize(480,280));
    FlexGridSizer3->Add(HtmlWindowPreview, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1 = new wxBoxSizer(wxVERTICAL);
    FlexGridSizer6 = new wxFlexGridSizer(0, 2, 0, 0);
    SpinCtrlImageCount = new wxSpinCtrl(this, ID_SPINCTRL2, _T("0"), wxDefaultPosition, wxSize(48,21), 0, 0, 100, 0, _T("ID_SPINCTRL2"));
    SpinCtrlImageCount->SetValue(_T("0"));
    SpinCtrlImageCount->Disable();
    FlexGridSizer6->Add(SpinCtrlImageCount, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    StaticText2 = new wxStaticText(this, ID_STATICTEXT2, _("Images"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT2"));
    FlexGridSizer6->Add(StaticText2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1->Add(FlexGridSizer6, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer5 = new wxFlexGridSizer(0, 2, 0, 0);
    SpinCtrlRowCount = new wxSpinCtrl(this, ID_SPINCTRL1, _T("1"), wxDefaultPosition, wxSize(48,21), 0, 1, 100, 1, _T("ID_SPINCTRL1"));
    SpinCtrlRowCount->SetValue(_T("1"));
    FlexGridSizer5->Add(SpinCtrlRowCount, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
    StaticText1 = new wxStaticText(this, ID_STATICTEXT1, _("Rows"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
    FlexGridSizer5->Add(StaticText1, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1->Add(FlexGridSizer5, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    CheckBoxFlipPan = new wxCheckBox(this, ID_CHECKBOX1, _("Flip Pan"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER, wxDefaultValidator, _T("ID_CHECKBOX1"));
    CheckBoxFlipPan->SetValue(false);
    BoxSizer1->Add(CheckBoxFlipPan, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
    CheckBoxFlipTilt = new wxCheckBox(this, ID_CHECKBOX2, _("Flip Tilt"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER, wxDefaultValidator, _T("ID_CHECKBOX2"));
    CheckBoxFlipTilt->SetValue(false);
    BoxSizer1->Add(CheckBoxFlipTilt, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer3->Add(BoxSizer1, 1, wxALIGN_TOP|wxALIGN_CENTER_HORIZONTAL, 5);
    StaticBoxSizer1->Add(FlexGridSizer3, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer1->Add(StaticBoxSizer1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer4 = new wxFlexGridSizer(0, 1, 0, 0);
    FlexGridSizer4->AddGrowableCol(0);
    ButtonShowHelp = new wxButton(this, ID_BUTTON3, _(">>"), wxDefaultPosition, wxSize(20,16), wxNO_BORDER, wxDefaultValidator, _T("ID_BUTTON3"));
    wxFont ButtonShowHelpFont(8,wxSWISS,wxFONTSTYLE_NORMAL,wxNORMAL,false,wxEmptyString,wxFONTENCODING_DEFAULT);
    ButtonShowHelp->SetFont(ButtonShowHelpFont);
    FlexGridSizer4->Add(ButtonShowHelp, 1, wxTOP|wxALIGN_LEFT|wxALIGN_TOP, 5);
    StaticBoxSizer3 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Help"));
    TextCtrlHelp = new wxTextCtrl(this, ID_TEXTCTRL2, _("mkqt converts images to a quicktime vr object movie\n\nUsage: mkqt.exe [path rows]\n\nmkqt.exe - without parameters, starting in GUI mode\n         - with paramaters, starting in console mode\npath     - path to a directory that contains the images\nrows     - number of rows used for image matrix creation"), wxDefaultPosition, wxDefaultSize, wxTE_NO_VSCROLL|wxTE_MULTILINE|wxTE_AUTO_URL|wxTE_DONTWRAP|wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE, wxDefaultValidator, _T("ID_TEXTCTRL2"));
    TextCtrlHelp->Disable();
    TextCtrlHelp->Hide();
    TextCtrlHelp->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER));
    wxFont TextCtrlHelpFont(8,wxSWISS,wxFONTSTYLE_NORMAL,wxNORMAL,false,_T("Courier New"),wxFONTENCODING_DEFAULT);
    TextCtrlHelp->SetFont(TextCtrlHelpFont);
    StaticBoxSizer3->Add(TextCtrlHelp, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer4->Add(StaticBoxSizer3, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer1->Add(FlexGridSizer4, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button1 = new wxButton(this, ID_BUTTON2, _("Make QTVR"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
    Button1->SetFocus();
    wxFont Button1Font(10,wxSWISS,wxFONTSTYLE_NORMAL,wxBOLD,false,wxEmptyString,wxFONTENCODING_DEFAULT);
    Button1->SetFont(Button1Font);
    FlexGridSizer1->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    SetSizer(FlexGridSizer1);
    DirDialogBrowse = new wxDirDialog(this, _("Select directory"), wxEmptyString, wxDD_DEFAULT_STYLE, wxDefaultPosition, wxDefaultSize, _T("wxDirDialog"));
    FlexGridSizer1->Fit(this);
    FlexGridSizer1->SetSizeHints(this);
    Center();

    Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&qtvrGUIDialog::OnButtonBrowseClick);
    Connect(ID_SPINCTRL1,wxEVT_COMMAND_SPINCTRL_UPDATED,(wxObjectEventFunction)&qtvrGUIDialog::OnSpinCtrlRowCountChange);
    Connect(ID_CHECKBOX1,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&qtvrGUIDialog::OnCheckBoxFlipPanClick);
    Connect(ID_CHECKBOX2,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&qtvrGUIDialog::OnCheckBoxFlipTiltClick);
    Connect(ID_BUTTON3,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&qtvrGUIDialog::OnButtonShowHelpClick);
    Connect(ID_BUTTON2,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&qtvrGUIDialog::OnButtonMakeQTVRClick);
    //*)

    imageCount = 0;
    windowWidth = GetSize().x;
    windowHeight = GetSize().y;
}

qtvrGUIDialog::~qtvrGUIDialog()
{
    //(*Destroy(qtvrGUIDialog)
    //*)
}

void qtvrGUIDialog::DrawImageMatrix()
{
    if(imageCount > 0)
    {
        wxUint32 rows = SpinCtrlRowCount->GetValue();
        wxUint32 cols = imageCount/rows;

        if(imageCount%rows == 0)
        {
            // Draw images depending on sort settings
            wxUint32 pos;

            wxString htmText = wxT("<table>");
            for(wxUint32 y=0; y<rows; y++)
            {
                htmText.Append(wxT("<tr>"));
                for(wxUint32 x=0; x<cols; x++)
                {
                    if(CheckBoxFlipTilt->GetValue())
                    {
                        pos = (rows-1-y)*cols;
                    }
                    else
                    {
                        pos = y*cols;
                    }
                    if(CheckBoxFlipPan->GetValue())
                    {
                        pos = pos+(cols-1-x);
                    }
                    else
                    {
                        pos = pos+x;
                    }
                    htmText.Append(wxT("<td><img width=\"100\" height=\"100\" src=\"") + imageFiles[pos] + wxT("\"></img></td>"));
                }
                htmText.Append(wxT("</tr>"));
            }
            htmText.Append(wxT("</table>"));

            HtmlWindowPreview->SetPage(htmText);
        }
        else
        {
            HtmlWindowPreview->SetPage(wxT("<center><br><br><b>INVALID ROW COUNT<br><br>PLEASE ENTER A VALID DIVIDER</b></center>"));
        }
    }
}

void qtvrGUIDialog::OnButtonBrowseClick(wxCommandEvent& event)
{
    if(DirDialogBrowse->ShowModal() == wxID_OK)
    {
        TextCtrlDirecory->SetValue(DirDialogBrowse->GetPath());

        wxString imgPath = DirDialogBrowse->GetPath();

        // Load images file path
        imageFiles.Clear();
        wxDirTraverserFiles fileTraverser(imageFiles);
        wxDir(imgPath).Traverse(fileTraverser, wxT(""), wxDIR_DEFAULT);

        // support only for png, bmp, jpg, gif, tif, tga, xpm
        // remove all other files from the file list
        for(wxUint32 i=0; i<imageFiles.Count(); i++)
        {
            if(!imageFiles[i].EndsWith(wxT(".png")) && !imageFiles[i].EndsWith(wxT(".bmp")) && !imageFiles[i].EndsWith(wxT(".jpg")) && !imageFiles[i].EndsWith(wxT(".gif")) && !imageFiles[i].EndsWith(wxT(".tif")) && !imageFiles[i].EndsWith(wxT(".tga")) && !imageFiles[i].EndsWith(wxT(".xpm")))
            {
                imageFiles.RemoveAt(i);
                i--;
            }
        }

        imageCount = imageFiles.Count();

        if(imageCount == 0)
        {
            wxMessageBox(wxT("No supported images found in the seleted directory!"));
            return;
        }

        SpinCtrlImageCount->SetValue(imageCount);
        SpinCtrlRowCount->SetValue(1);
        SpinCtrlRowCount->SetMax(imageCount);
        CheckBoxFlipPan->SetValue(false);
        CheckBoxFlipTilt->SetValue(false);

        DrawImageMatrix();
    }
}

void qtvrGUIDialog::OnButtonMakeQTVRClick(wxCommandEvent& event)
{
    // make QTVR from imageMatrix depending on sort settings
    if(imageCount > 0)
    {
        wxUint32 rows = SpinCtrlRowCount->GetValue();
        wxUint32 cols = imageCount/rows;

        if(imageCount%rows == 0)
        {
            wxUint32 pos;
            wxUint32 count = 0;

            // Create image matrix...
            wxImage* imageMatrix = new wxImage[imageCount];

            for(wxUint32 y=0; y<rows; y++)
            {
                for(wxUint32 x=0; x<cols; x++)
                {
                    if(CheckBoxFlipTilt->GetValue())
                    {
                        pos = (rows-1-y)*cols;
                    }
                    else
                    {
                        pos = y*cols;
                    }
                    if(CheckBoxFlipPan->GetValue())
                    {
                        pos = pos+(cols-1-x);
                    }
                    else
                    {
                        pos = pos+x;
                    }
                    wxPrintf(wxT("Loading: ") + imageFiles[pos].AfterLast('\\') + wxT("\n"));
                    imageMatrix[count] = wxImage(imageFiles[pos]);
                    // define jpg quality for this image, when exporting into the qtvr movie
                    imageMatrix[count].SetOption(wxT("quality"), 85);
                    count++;
                }
            }
            wxPrintf(wxT("\nMAKE QTVR COMPLETE\n\n"));

            // create an QTVR instance based on the images and save this to the output file
            QT qt(imageMatrix, imageCount, cols, rows);
            qt.save(TextCtrlDirecory->GetValue() + wxT("\\output.mov"));

            // free memory
            wxDELETEA(imageMatrix);

            wxMessageBox(wxT("QTVR Movie was created:\n") + TextCtrlDirecory->GetValue() + wxT("\\output.mov"));
        }
        else
        {
            wxMessageBox(wxT("Number of rows is not a valid divisor for the number of images in the given directory!"));
        }
    }
    else
    {
        wxMessageBox(wxT("No supported images found in the given directory (png|bmp|jpg|gif|tif|tga|xpm)!"));
    }
}

void qtvrGUIDialog::OnCheckBoxFlipPanClick(wxCommandEvent& event)
{
    DrawImageMatrix();
}

void qtvrGUIDialog::OnCheckBoxFlipTiltClick(wxCommandEvent& event)
{
    DrawImageMatrix();
}

void qtvrGUIDialog::OnSpinCtrlRowCountChange(wxSpinEvent& event)
{
    DrawImageMatrix();
}

void qtvrGUIDialog::OnButtonShowHelpClick(wxCommandEvent& event)
{
    if(ButtonShowHelp->GetLabel() == wxT(">>"))
    {
        ButtonShowHelp->SetLabel(wxT("<<"));
        TextCtrlHelp->Show();
    }
    else
    {
        ButtonShowHelp->SetLabel(wxT(">>"));
        TextCtrlHelp->Hide();
    }

    if(this->IsMaximized())
    {
        Layout();
    }
    else
    {
        // currently change the min size for html window to prevent minimize operation of fit
        wxSize minSize = HtmlWindowPreview->GetMinSize();
        HtmlWindowPreview->SetMinSize(HtmlWindowPreview->GetSize());

        Fit();

        // set the min size for html window back to initial state
        HtmlWindowPreview->SetMinSize(minSize);
    }
}
